#include "my_string.h"
#include <cstring>


MyString::MyString()
    : data_(new char[1]), size_(1) {
    data_[0] = '\0';
}


MyString::MyString(const char* str)
    : size_(strlen(str) + 1) {
    data_ = new char[size_];
    strcpy(data_, str);
}


MyString::MyString(const MyString& str)
    : size_(str.size_) {
    data_ = new char[size_];
    strcpy(data_, str.data_);
}



MyString::~MyString() {
    delete[] data_;
}


int MyString::size() const {
    int size = 0;
    while (data_[size] != '\0') {
        size++;
    }
    return size;
}


int MyString::max_size() const {
    return size_ - 1;
}


MyString& MyString::operator=(const MyString& str) {
    // 一般情况下，赋值运算符都会先判断是否是自我赋值
    if (this == &str) {
        return *this;
    }

    // 如果不是自我赋值，那么先释放原来的内存，然后再重新分配内存并复制
    delete[] data_;
    size_ = str.size_;
    data_ = new char[size_];
    strcpy(data_, str.data_);
    return *this;
}


// 思考：如果 + 写成成员函数，会有什么问题？
// MyString MyString::operator+(const MyString& rhs) const {
//     MyString result;
//     result.expand(size() + rhs.size() + 1);     // 要考虑 '\0'
//     strcpy(result.data_, data_);
//     strcat(result.data_, rhs.data_);
//     return result;
// }

MyString operator+(const MyString& lhs, const MyString& rhs) {
    MyString result;
    result.expand(lhs.size() + rhs.size() + 1);    // 要考虑 '\0'
    strcpy(result.data_, lhs.data_);
    strcat(result.data_, rhs.data_);
    return result;
}


MyString& MyString::operator+=(const MyString& str) {
    *this = *this + str;
    return *this;
}


bool MyString::operator==(const MyString& str) const {
    return strcmp(data_, str.data_) == 0;
}


std::ostream& operator<<(std::ostream& os, const MyString& str) {
    os << str.data_;
    return os;
}


char& MyString::operator[](int index) {
    if (index < 0 || index >= size()) {
        // 这里不用看懂，这里 可以简单理解为 index 越界了，下面的代码让程序崩溃
        throw std::out_of_range("index out of range");
    }
    return data_[index];
}


const char& MyString::operator[](int index) const {
    if (index < 0 || index >= size()) {
        throw std::out_of_range("index out of range");
    }
    return data_[index];
}


void MyString::expand(int need_size) {
    // 扩展思路：不断 *2，扩展到 size_ >= need_size 为止
    while (size_ <= need_size) {
        size_ *= 2;
    }
    char* new_data = new char[size_];
    strcpy(new_data, data_);
    delete[] data_;
    data_ = new_data;
}
